import time

import matplotlib.pyplot as plt
from keras.models import load_model
from keras import models
from keras_preprocessing import image  # 将图像预处理为一个4D张量
from keras import backend as k
from keras.applications import VGG16
import numpy as np

model = load_model('cats_and_dogs_small_2.h5')
# 查看特征图维度变化
# model.summary()
img_path = r'D:\Users\kk\PycharmProjects\pythonProject\pythonProject2\tt\demo02\cats_and_dogs_small\test\cats\cat.1500.jpg'

# 图片预处理
img = image.load_img(img_path, target_size=(150, 150))

img_tensor = image.img_to_array(img)
img_tensor = np.expand_dims(img_tensor, axis=0)
img_tensor /= 255.

# 输出形状信息
# print(img_tensor.shape)

# 显示测试图像
# plt.imshow(img_tensor[0])
# plt.show()

layer_outputs = [layer.output for layer in model.layers[:8]]  # 提取前8层的输出
# 创建一个模型，给定模型输入，可以返回这些输出
activation_model = models.Model(inputs=model.input, outputs=layer_outputs)

activations = activation_model.predict(img_tensor)  # 返回8个Numpy数组组成的列表
# 第一个卷积层的激活（1，148，32）
# first_layer_activation = activations[0]
# print(first_layer_activation.shape)

# 卷积层可视化(特征图可视化)
'''
first_layer_activation = activations[0]
plt.matshow(first_layer_activation[0, :, :, 1], cmap='viridis')
plt.show()
'''
layer_names = []  # 层名称
for layer in model.layers[:8]:
    layer_names.append(layer.name)

images_per_row = 16

for layer_name, layer_activation in zip(layer_names, activations):
    # shape属性（1, size, size, n_features）
    n_features = layer_activation.shape[-1]
    size = layer_activation.shape[1]
    '''
    在这个矩阵中将激活通道平铺
    '''
    n_cols = n_features // images_per_row
    display_grid = np.zeros((size * n_cols, images_per_row * size))
    for col in range(n_cols):
        '''
        将每个过滤器平铺到一个大的水平网格中
        '''
        for row in range(images_per_row):
            '''
            对特征进行后处理，使其观看美观
            '''
            channel_image = layer_activation[0, :, :, col * images_per_row + row]
            channel_image -= channel_image.mean()  # 取平均值
            channel_image /= channel_image.std()  # 标准差
            channel_image *= 64
            channel_image += 128
            channel_image = np.clip(channel_image, 0, 255).astype('uint8')
            display_grid[col * size: (col + 1) * size, row * size: (row + 1) * size] = channel_image

        scale = 1. / size
        plt.figure(figsize=(scale * display_grid.shape[1],
                            scale * display_grid.shape[0]))
        plt.title(layer_name)
        plt.grid(False)
        plt.imshow(display_grid, aspect='auto', cmap='viridis')
        plt.show()